##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2023 XHH <xhh@example.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, see <http://www.gnu.org/licenses/>.
##

import sigrokdecode as srd

class ChannelError(Exception):
    pass

class Decoder(srd.Decoder):
    api_version = 3
    id = 'xhh_8bit'
    name = 'xhh_8bit'
    longname = 'xhh_8bit'
    desc = 'xhh_8bit'
    license = 'gplv2+'
    inputs = ['logic']
    outputs = []
    tags = ['Encoding']
    channels = (
        {'id': 'bit0', 'name': 'Bit0', 'desc': 'Bit 0 (LSB)', 'default': 0},
        {'id': 'bit1', 'name': 'Bit1', 'desc': 'Bit 1', 'default': 1},
        {'id': 'bit2', 'name': 'Bit2', 'desc': 'Bit 2', 'default': 2},
        {'id': 'bit3', 'name': 'Bit3', 'desc': 'Bit 3', 'default': 3},
        {'id': 'bit4', 'name': 'Bit4', 'desc': 'Bit 4', 'default': 4},
        {'id': 'bit5', 'name': 'Bit5', 'desc': 'Bit 5', 'default': 5},
        {'id': 'bit6', 'name': 'Bit6', 'desc': 'Bit 6', 'default': 6},
        {'id': 'bit7', 'name': 'Bit7', 'desc': 'Bit 7 (MSB)', 'default': 7},
    )
    options = (
        {'id': 'polarity', 'desc': 'Logic polarity',
            'default': 'active-high', 'values': ('active-high', 'active-low')},
    )
    annotations = (
        ('decoded-value', 'Decoded value'),
        ('binary-value', 'Binary value'),
    )
    annotation_rows = (
        ('decoded-values', 'Decoded values', (0,)),
        ('binary-values', 'Binary values', (1,)),
    )

    def __init__(self):
        self.reset()

    def reset(self):
        self.bit0 = 0
        self.bit1 = 1
        self.bit2 = 2
        self.bit3 = 3
        self.bit4 = 4
        self.bit5 = 5
        self.bit6 = 6
        self.bit7 = 7
        pass

    def start(self):
        self.out_ann = self.register(srd.OUTPUT_ANN)

    def putb(self, ss_block, es_block, data):
        self.put(ss_block, es_block, self.out_ann, data)

    def binary_to_decimal(self, bits):
        # 将8位二进制信号转换为十进制值
        decimal_value = 0
        for i in range(8):
            decimal_value |= (bits[i] << i)
        return decimal_value
    
    def binary_to_hex(self, bits):
        # 将8位二进制信号转换为十六进制值
        hex_value = 0
        for i in range(8):
            hex_value |= (bits[i] << i)
        return hex(hex_value)

    def bits_to_binary_str(self, bits):
        # 将信号转换为二进制字符串（显示时从MSB到LSB）
        binary_str = ''
        for i in range(7, -1, -1):  # 从MSB到LSB
            binary_str += str(bits[i])
        return binary_str

    def decode(self):
        # 等待所有8个信号
        (bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7) = self.wait()
        old_bits = [bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7]

        # 检查所有8个信号是否都存在
        if False in [p in (0, 1) for p in old_bits]:
            raise ChannelError('All 8 bits must be present.')

        last_pos = self.samplenum

        # 设置触发条件：任何一个信号改变都触发
        conditions = [
            {0: 'e'}, {1: 'e'}, {2: 'e'}, {3: 'e'}, 
            {4: 'e'}, {5: 'e'}, {6: 'e'}, {7: 'e'}
        ]

        while True:
            # 等待任何信号变化
            (bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7) = self.wait(conditions)
            bits = [bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7]

            # 处理极性，如果是active-low则反转信号
            if self.options['polarity'] == 'active-low':
                old_bits = [1 - b for b in old_bits]

            # 计算十进制值
            decimal_value = self.binary_to_decimal(old_bits)
            # 计算十六进制值
            hex_value = self.binary_to_hex(old_bits)
            
            # 获取二进制字符串（MSB到LSB顺序显示）
            binary_str = self.bits_to_binary_str(old_bits)

            # 输出十进制值和二进制表示
            self.putb(last_pos, self.samplenum, [0, [str(hex_value) + '~' + str(decimal_value)]])
            self.putb(last_pos, self.samplenum, [1, [binary_str]])
        
            # 更新状态
            last_pos = self.samplenum
            old_bits = bits
